package com.ev.apis.controller.asl;

import cn.afterturn.easypoi.entity.vo.TemplateExcelConstants;
import cn.afterturn.easypoi.excel.entity.TemplateExportParams;
import cn.afterturn.easypoi.view.PoiBaseView;
import cn.hutool.core.util.ObjectUtil;
import com.ev.apis.model.DsResultResponse;
import com.ev.asl.constant.AslConstant;
import com.ev.asl.domain.AssemblyInstructionDO;
import com.ev.asl.service.AssemblyInstructionService;
import com.ev.framework.annotation.EvApiByToken;
import com.ev.framework.utils.DateUtils;
import com.ev.framework.utils.JSONUtils;
import com.ev.framework.utils.R;
import com.ev.framework.utils.ShiroUtils;
import com.ev.mes.domain.ProductionPlanDO;
import com.ev.mes.service.ProductionPlanService;
import com.ev.system.domain.UserDO;
import com.google.common.collect.Maps;
import io.swagger.annotations.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.ui.ModelMap;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.util.*;

/**
 * 组装指示书API
 * @author 姚家乐
 * @since 2021/5/26 9:57
 */
@Api(value = "/", tags = "组装指示书API")
@RestController
public class AssemblyInstructionApiController {

    @Autowired
    private AssemblyInstructionService service;

    @Autowired
    private ProductionPlanService      productionPlanService;

    /**
     * 保存组装指示信息
     *
     * @date 2019-11-27
     * @author gumingjie
     */
    @Transactional(rollbackFor = Exception.class)
    @EvApiByToken(value = "/apis/AssemblyInstruction/save", method = RequestMethod.POST, apiTitle = "保存组装指示信息")
    @ApiOperation("保存组装指示信息")
    //    @ApiImplicitParams({ @ApiImplicitParam(name = "indicateDate", value = "日期", dataType = "Date"),
    //                         @ApiImplicitParam(name = "serialNo", value = "指示编号", dataType = "String"),
    //                         @ApiImplicitParam(name = "workTime", value = "工作时间", dataType = "Number"),
    //                         @ApiImplicitParam(name = "productionPlanId", value = "k3生产任务单id", dataType = "int"),
    //                         @ApiImplicitParam(name = "specialNoteItem", value = "特记事项", dataType = "String") })
    public R save(AssemblyInstructionDO entity) {
        if (!ObjectUtils.isEmpty(entity) && !ObjectUtils.isEmpty(entity.getProductionPlanId())){
            ProductionPlanDO productionPlanDO = productionPlanService.get(entity.getProductionPlanId());
            entity.setPlanCode(productionPlanDO.getPlanNo());
            entity.setPlanId(productionPlanDO.getId());
        }
        UserDO userDO = ShiroUtils.getUser();
        if (userDO != null) {
            entity.setStaffingId(userDO.getUserId());
            entity.setStaffingName(userDO.getName());
        }

        entity.setResidue(ObjectUtils.isEmpty(entity.getQty()) ? BigDecimal.ZERO : entity.getQty());
        if (service.save(entity) > 0) {
//            ProductionPlanDO productionPlanDO = new ProductionPlanDO();
//            productionPlanDO.setId(entity.getProductionPlanId());
//            productionPlanDO.setHaveMpi(AslConstant.YES);
//            productionPlanService.update(productionPlanDO);
            Map<String, Object> result = Maps.newHashMapWithExpectedSize(1);
            result.put("id", entity.getId());
            return R.ok(result);
        }
        return R.error();
    }

    /**
     * 查看组装指示详情
     *
     * @date 2019-11-27
     * @author gumingjie
     */
    @EvApiByToken(value = "/apis/AssemblyInstruction/detail", method = RequestMethod.POST, apiTitle = "查看组装指示详情")
    @ApiOperation("查看组装指示详情")
    public R detail(@ApiParam(value = "组装指示Id", required = true) @RequestParam(value = "id", defaultValue = "") Long id) {
        return R.ok(service.getDetailInfo(id));
    }

    /**
     * 修改组装指示
     * @param entity
     * @return
     */
    @EvApiByToken(value = "/apis/AssemblyInstruction/update", method = RequestMethod.POST, apiTitle = "修改组装指示")
    @ApiOperation("修改组装指示")
    public R update(AssemblyInstructionDO entity) {
        AssemblyInstructionDO assemblyInstructionDO = service.get(entity.getId());
        if (!ObjectUtils.isEmpty(entity) && !ObjectUtils.isEmpty(entity.getProductionPlanId()) && !entity.getProductionPlanId().equals(assemblyInstructionDO.getPlanId())){
            ProductionPlanDO productionPlanDO = productionPlanService.get(entity.getProductionPlanId());
            entity.setPlanCode(productionPlanDO.getPlanNo());
            entity.setPlanId(productionPlanDO.getId());
        }
        if (AslConstant.AssemblyInstruction.PLAN.getType()
                .equals(assemblyInstructionDO.getStatus())) {
            int update = service.update(entity);
            if (update > 0) {
                return R.ok();
            }
            return R.error();
        }

        return R.error("非计划状态不能修改！");
    }

    /**
     * 删除
     */
    @EvApiByToken(value = "/apis/AssemblyInstruction/batchRemove", method = RequestMethod.POST, apiTitle = "删除组装指示")
    @ApiOperation("删除组装指示")
    public R batchRemove(@RequestParam("ids") Long[] ids) {
        Map<String, Object> pm = new HashMap<>();
        pm.put("ids", Arrays.asList(ids));
        List<AssemblyInstructionDO> list = service.list(pm);

        ids = list.stream().filter(e -> AslConstant.AssemblyInstruction.PLAN
                .getType().equals(e.getStatus())).map(AssemblyInstructionDO::getId).toArray(Long[]::new);
        if (ids.length > AslConstant.ZERO){
            int remove = service.batchRemove(ids);
            if (remove > 0) {
                return R.ok("删除成功");
            }
            return R.error("删除失败");
        }
        return R.error("删除失败");
    }

    /**
     * 删除
     */
    @EvApiByToken(value = "/apis/AssemblyInstruction/remove", method = RequestMethod.POST, apiTitle = "删除组装指示")
    @ApiOperation("删除组装指示")
    public R remove(@RequestParam("id") Long id) {
        AssemblyInstructionDO assemblyInstructionDO = service.get(id);
        if (AslConstant.AssemblyInstruction.PLAN.getType()
                .equals(assemblyInstructionDO.getStatus())) {
            int remove = service.remove(id);
            if (remove > 0) {
                return R.ok("删除成功");
            }
            return R.error("删除失败");
        }
        return R.error("删除失败");
    }

    /**
     * 审查
     */
    @EvApiByToken(value = "/apis/AssemblyInstruction/investigate", method = RequestMethod.GET, apiTitle = "审查组装指示")
    @ApiOperation("审查组装指示")
    public R investigate(@RequestParam("id") Long id) {

        UserDO userDO = ShiroUtils.getUser();

        AssemblyInstructionDO assemblyInstructionDO = service.get(id);
        if (AslConstant.AssemblyInstruction.PLAN.getType()
                .equals(assemblyInstructionDO.getStatus())) {
            assemblyInstructionDO
                    .setStatus(AslConstant.AssemblyInstruction.AUDITOR.getType());
            assemblyInstructionDO.setAuditorId(userDO.getUserId());
            assemblyInstructionDO.setAuditorName(userDO.getName());
            int update = service.update(assemblyInstructionDO);
            if (update > 0) {
                return R.ok();
            }
            return R.error();
        }
        return R.error();
    }

    /**
     * 反审查
     */
    @EvApiByToken(value = "/apis/AssemblyInstruction/reverseInvestigate", method = RequestMethod.GET, apiTitle = "反审查组装指示")
    @ApiOperation("反审查组装指示")
    public R reverseInvestigate(@RequestParam("id") Long id, HttpServletRequest request) {
        AssemblyInstructionDO assemblyInstructionDO = service.get(id);
        if (AslConstant.AssemblyInstruction.AUDITOR.getType()
                .equals(assemblyInstructionDO.getStatus())) {
            assemblyInstructionDO
                    .setStatus(AslConstant.AssemblyInstruction.PLAN.getType());
            assemblyInstructionDO.setAuditorId(null);
            assemblyInstructionDO.setAuditorName(null);
            int update = service.update(assemblyInstructionDO);
            if (update > 0) {
                return R.ok();
            }
            return R.error();
        }
        return R.error("当前状态不能反审查！");
    }

    /**
     * 批准
     */
    @EvApiByToken(value = "/apis/AssemblyInstruction/ratify", method = RequestMethod.GET, apiTitle = "批准组装指示")
    @ApiOperation("批准组装指示")
    public R ratify(@RequestParam("id") Long id, HttpServletRequest request) {
        UserDO userDO = ShiroUtils.getUser();

        AssemblyInstructionDO assemblyInstructionDO = service.get(id);
        if (AslConstant.AssemblyInstruction.AUDITOR.getType()
                .equals(assemblyInstructionDO.getStatus())) {
            assemblyInstructionDO
                    .setStatus(AslConstant.AssemblyInstruction.APPROVED.getType());
            assemblyInstructionDO.setApproverId(userDO.getUserId());
            assemblyInstructionDO.setApproverName(userDO.getName());
            int update = service.update(assemblyInstructionDO);
            if (update > 0) {
                return R.ok();
            }
            return R.error();
        }
        return R.error();
    }

    /**
     * 反批准
     */
    @EvApiByToken(value = "/apis/AssemblyInstruction/reverseRatify", method = RequestMethod.GET, apiTitle = "反批准组装指示")
    @ApiOperation("反批准组装指示")
    public R reverseRatify(@RequestParam("id") Long id, HttpServletRequest request) {

        AssemblyInstructionDO assemblyInstructionDO = service.get(id);
        if (AslConstant.AssemblyInstruction.APPROVED.getType()
                .equals(assemblyInstructionDO.getStatus())) {
            assemblyInstructionDO
                    .setStatus(AslConstant.AssemblyInstruction.AUDITOR.getType());
            assemblyInstructionDO.setApproverId(null);
            assemblyInstructionDO.setApproverName(null);

            int update = service.update(assemblyInstructionDO);
            if (update > 0) {
                return R.ok();
            }
            return R.error();
        }

        return R.error("当前状态不能反批准！");
    }

    /**
     * 开工
     */
    @EvApiByToken(value = "/apis/AssemblyInstruction/startWork", method = RequestMethod.GET, apiTitle = "开工组装指示")
    @ApiOperation("开工组装指示")
    public R startWork(@RequestParam("id") Long id) {
        AssemblyInstructionDO assemblyInstructionDO = service.get(id);
        if (AslConstant.AssemblyInstruction.APPROVED.getType()
                .equals(assemblyInstructionDO.getStatus())
                || AslConstant.AssemblyInstruction.SUSPENDED_STATE.getType()
                .equals(assemblyInstructionDO.getStatus())) {
            assemblyInstructionDO
                    .setStatus(AslConstant.AssemblyInstruction.HAS_COMMENCED.getType());
            int update = service.update(assemblyInstructionDO);
            if (update > 0) {
                return R.ok();
            }
            return R.error();
        }

        return R.error();
    }

    /**
     * 挂起
     */
    @EvApiByToken(value = "/apis/AssemblyInstruction/putUp", method = RequestMethod.GET, apiTitle = "挂起组装指示")
    @ApiOperation("挂起组装指示")
    public R putUp(@RequestParam("id") Long id) {
        AssemblyInstructionDO assemblyInstructionDO = service.get(id);
        if (AslConstant.AssemblyInstruction.HAS_COMMENCED.getType()
                .equals(assemblyInstructionDO.getStatus())) {
            assemblyInstructionDO.setStatus(
                    AslConstant.AssemblyInstruction.SUSPENDED_STATE.getType());
            int update = service.update(assemblyInstructionDO);
            if (update > 0) {
                return R.ok();
            }
            return R.error();
        }
        return R.error();
    }

    /**
     * 结案
     */
    @EvApiByToken(value = "/apis/AssemblyInstruction/close", method = RequestMethod.GET, apiTitle = "结案组装指示")
    @ApiOperation("结案组装指示")
    public R close(@RequestParam("id") Long id) {
        AssemblyInstructionDO assemblyInstructionDO = service.get(id);
        if (AslConstant.AssemblyInstruction.HAS_COMMENCED.getType()
                .equals(assemblyInstructionDO.getStatus())
                || AslConstant.AssemblyInstruction.SUSPENDED_STATE.getType()
                .equals(assemblyInstructionDO.getStatus())) {
            assemblyInstructionDO
                    .setStatus(AslConstant.AssemblyInstruction.CASE_BEEN.getType());
            int update = service.update(assemblyInstructionDO);
            if (update > 0) {
                return R.ok();
            }
            return R.error();
        }
        return R.error();
    }

    /**
     * 反结案
     */
    @EvApiByToken(value = "/apis/AssemblyInstruction/reverseClose", method = RequestMethod.GET, apiTitle = "反结案组装指示")
    @ApiOperation("反结案组装指示")
    public R reverseClose(@RequestParam("id") Long id) {
        AssemblyInstructionDO assemblyInstructionDO = service.get(id);
        if (AslConstant.AssemblyInstruction.CASE_BEEN.getType()
                .equals(assemblyInstructionDO.getStatus())) {
            assemblyInstructionDO
                    .setStatus(AslConstant.AssemblyInstruction.HAS_COMMENCED.getType());
            int update = service.update(assemblyInstructionDO);
            if (update > 0) {
                return R.ok();
            }
            return R.error();
        }
        return R.error("当前状态不能反结案！");
    }


    /**
     * 查看组装指示分页列表
     * @param pageno
     * @param pagesize
     * @param delFlag
     * @param serialNo
     * @param materielName
     * @param indicateDateStart
     * @param indicateDateEnd
     * @return
     */
    @EvApiByToken(value = "/apis/AssemblyInstruction/list", method = RequestMethod.POST, apiTitle = "查看组装指示分页列表")
    @ApiOperation("查看组装指示分页列表")
    public R list(@ApiParam(value = "当前第几页", required = true) @RequestParam(value = "pageno", defaultValue = "1") int pageno,
                  @ApiParam(value = "一页多少条", required = true) @RequestParam(value = "pagesize", defaultValue = "20") int pagesize,
                  @ApiParam(value = "刪除状态") @RequestParam(value = "delFlag", defaultValue = "", required = false) Integer delFlag,
                  @ApiParam(value = "指示编号") @RequestParam(value = "serialNo", defaultValue = "", required = false) String serialNo,
                  @ApiParam(value = "状态") @RequestParam(value = "status", defaultValue = "", required = false) Integer status,
                  @ApiParam(value = "剩余数量大于0") @RequestParam(value = "residue", defaultValue = "", required = false) Integer residue,
                  @ApiParam(value = "状态集合") @RequestParam(value = "statusList", defaultValue = "", required = false) List<Integer> statusList,
                  @ApiParam(value = "品名") @RequestParam(value = "materielName", defaultValue = "", required = false) String materielName,
                  @ApiParam(value = "日期的起始时间") @RequestParam(value = "indicateDateStart", defaultValue = "", required = false) Date indicateDateStart,
                  @ApiParam(value = "日期的结束时间") @RequestParam(value = "indicateDateEnd", defaultValue = "", required = false) Date indicateDateEnd,
                  @ApiParam(value = "是否首检(0:未首检，1：已首检)") @RequestParam(value = "haveFirstCheck", defaultValue = "", required = false) Integer haveFirstCheck) {

        Map<String, Object> params = Maps.newHashMapWithExpectedSize(10);
        params.put("offset", (pageno - 1) * pagesize);
        params.put("limit", pagesize);
        params.put("delFlag", delFlag);
        params.put("status", status);
        params.put("statusList", statusList);
        params.put("serialNo", serialNo);
        params.put("materielName", materielName);
        params.put("indicateDateStart", indicateDateStart);
        params.put("indicateDateEnd", indicateDateEnd);
        params.put("residue", residue);
//        params.put("haveFirstCheck", haveFirstCheck);

        Map<String, Object> results = Maps.newHashMapWithExpectedSize(1);
        List<Map<String, Object>> data = service.listForMap(params);

        if (data.size() > 0) {
            int total = service.countForMap(params);

            params.remove("offset");
            params.remove("limit");
            List<Map<String, Object>> data2 = service.listForMap(params);
            BigDecimal qtyTotal = BigDecimal.ZERO;
            for (Map<String, Object> map : data2) {
                qtyTotal = qtyTotal
                        .add(new BigDecimal(String.valueOf(map.get("qty") != null ? map.get("qty") : "0")));
            }
            for (Map<String,Object> map : data){
//                map.put("indicateDate", DateUtils.format((Date) map.get("indicateDate")));
                map.put("startDate", ObjectUtil.isEmpty(map.get("startDate")) ? null : DateUtils.format((Date) map.get("startDate"), "yyyy-MM-dd HH:mm:ss"));
                map.put("endDate", ObjectUtil.isEmpty(map.get("endDate")) ? null : DateUtils.format((Date) map.get("endDate"), "yyyy-MM-dd HH:mm:ss"));
            }

            Map<String, Object> result = Maps.newHashMapWithExpectedSize(4);
            result.put("data", new DsResultResponse(pageno, pagesize, total, data));
            result.put("qtyTotal", qtyTotal);
            results.put("data", result);
        }
        return R.ok(results);
    }

    @EvApiByToken(value = "/apis/AssemblyInstruction/list/exportExcel", method = RequestMethod.POST, apiTitle = "成型生产指示分页列表(导出)")
    @ApiOperation("成型生产指示分页列表(导出)")
    public void exportExcel(@ApiParam(value = "刪除状态") @RequestParam(value = "delFlag", defaultValue = "", required = false) Integer delFlag,
                            @ApiParam(value = "指示编号") @RequestParam(value = "serialNo", defaultValue = "", required = false) String serialNo,
                            @ApiParam(value = "品名") @RequestParam(value = "materielName", defaultValue = "", required = false) String materielName,
                            @ApiParam(value = "日期的起始时间") @RequestParam(value = "indicateDateStart", defaultValue = "", required = false) Date indicateDateStart,
                            @ApiParam(value = "日期的结束时间") @RequestParam(value = "indicateDateEnd", defaultValue = "", required = false) Date indicateDateEnd,
                            HttpServletRequest request, HttpServletResponse response,
                            ModelMap modelMap) {
        Map<String, Object> params = Maps.newHashMapWithExpectedSize(5);
        params.put("delFlag", delFlag);
        params.put("serialNo", serialNo);
        params.put("materielName", materielName);
        params.put("indicateDateStart", indicateDateStart);
        params.put("indicateDateEnd", indicateDateEnd);
        List<Map<String, Object>> data = service.listForMap(params);
        if (!CollectionUtils.isEmpty(data)) {

            BigDecimal qtyTotal = BigDecimal.ZERO;
            for (Map<String, Object> map : data) {
                map.put("indicateDateString", DateUtils.format((Date) map.get("indicateDate")));
                qtyTotal = qtyTotal
                        .add(new BigDecimal(String.valueOf(map.get("qty") != null ? map.get("qty") : "0")))
                        .setScale(2, BigDecimal.ROUND_HALF_UP);
            }

            Map<String, Object> map = Maps.newHashMap();
            map.put("list", JSONUtils.format(data));
            map.put("qtyTotal", qtyTotal);

            ClassPathResource classPathResource = new ClassPathResource(
                    "poi/assembly_instruction.xlsx");
            TemplateExportParams result = new TemplateExportParams(classPathResource.getPath());
            modelMap.put(TemplateExcelConstants.FILE_NAME, "附属件组装指示");
            modelMap.put(TemplateExcelConstants.PARAMS, result);
            modelMap.put(TemplateExcelConstants.MAP_DATA, map);
            PoiBaseView.render(modelMap, request, response,
                    TemplateExcelConstants.EASYPOI_TEMPLATE_EXCEL_VIEW);
        }
    }
}
